package org.luckystrophe.snowtoms.manager;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.luckystrophe.snowtoms.application.GlobalApplication;

import android.content.ContentResolver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.util.Log;

import com.googlecode.androidannotations.annotations.EBean;
import com.googlecode.androidannotations.api.Scope;

@EBean(scope = Scope.Singleton)
public class ImageManager {

	private static final String TMP_DIRECTORY = "Android/data/" + GlobalApplication.PACKAGE_NAME + "/files";

	public static Uri createSaveCropFile() {
		String url = "tmp_" + String.valueOf(System.currentTimeMillis()) + ".jpg";
		File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), TMP_DIRECTORY);
		if (!dir.isDirectory()) {
			dir.mkdirs();
		}
		Uri uri = Uri.fromFile(new File(dir, url));
		return uri;
	}

	public static Bitmap getImageFromUri(ContentResolver resolver, Uri currImageUri) {
		Bitmap bm = null;
		try {
			bm = Images.Media.getBitmap(resolver, currImageUri);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bm;
	}

	public static void autoCropImage(ContentResolver resolver, Uri currImageUri) {
		try {
			Bitmap bm = Images.Media.getBitmap(resolver, currImageUri);
			Bitmap dstBm = null;
			int bmWidth = bm.getWidth();
			int bmHeight = bm.getHeight();

			if (bmWidth >= bmHeight) {

				dstBm = Bitmap.createBitmap(bm, bmWidth / 2 - bmHeight / 2, 0, bmHeight, bmHeight);

			} else {

				dstBm = Bitmap.createBitmap(bm, 0, bmHeight / 2 - bmWidth / 2, bmWidth, bmWidth);
			}
			String url = Images.Media.insertImage(resolver, dstBm, null, null);
			Log.e("Mas", url);

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static File getImageFile(Uri uri, ContentResolver resolver) {
		String[] projection = { MediaStore.Images.Media.DATA };
		if (uri == null) {
			uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
		}

		Cursor mCursor = resolver.query(uri, projection, null, null, MediaStore.Images.Media.DATE_MODIFIED + " desc");
		if (mCursor == null || mCursor.getCount() < 1) {
			return null;
		}
		int column_index = mCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		mCursor.moveToFirst();

		String path = mCursor.getString(column_index);

		if (mCursor != null) {
			mCursor.close();
			mCursor = null;
		}
		return new File(path);
	}

	public static boolean copyFile(File srcFile, File destFile) {
		boolean result = false;
		try {
			String originalFilePath = srcFile.getPath();
			// long standardSize = 500 * 1024;
			// int sampleSize = (int) (srcFile.length() / standardSize);
			//
			// if (sampleSize == 1) {
			// sampleSize++;
			// } else if (sampleSize > 2) {
			// sampleSize = 2;
			// }
			OutputStream out = new FileOutputStream(destFile);

			BitmapFactory.Options o = new BitmapFactory.Options();
			o.inJustDecodeBounds = true;
			FileInputStream inputStream = new FileInputStream(srcFile);
			BitmapFactory.decodeStream(inputStream, null, o);
			inputStream.close();

			// final int REQUIRED_SIZE = 600;
			int width_tmp = o.outWidth, height_tmp = o.outHeight;
			// int scale = 1;
			// while (true) {
			// if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 <
			// REQUIRED_SIZE)
			// break;
			// width_tmp /= 2;
			// height_tmp /= 2;
			// scale *= 2;
			// }

			try {
				int standardWidth = 720;
				int standardHeight = 960;

				int finalWidth = 0;
				int finalHeight = 0;

				int sampleCount = height_tmp > 1980 || width_tmp > 1440 ? 2 : 1;

				BitmapFactory.Options options = new BitmapFactory.Options();
				options.inSampleSize = sampleCount;
				FileInputStream inputStream2 = new FileInputStream(srcFile);
				Bitmap reducedBM = BitmapFactory.decodeStream(inputStream2, null, options);
				inputStream2.close();
				int degree = getExifOrientation(originalFilePath);
				reducedBM = getRotatedBitmap(reducedBM, degree);
				width_tmp = reducedBM.getWidth();
				height_tmp = reducedBM.getHeight();

				if (width_tmp > standardWidth && height_tmp > standardHeight) {
					float compressRatio = 1.0f;
					if (width_tmp > height_tmp) {
						compressRatio = (float) width_tmp / standardWidth;
					} else {
						compressRatio = (float) height_tmp / standardHeight;
					}
					finalWidth = (int) (width_tmp / compressRatio);
					finalHeight = (int) (height_tmp / compressRatio);

				} else if (width_tmp > standardWidth) {
					float ratio = (float) width_tmp / standardWidth;
					finalWidth = standardWidth;
					finalHeight = (int) (height_tmp / ratio);
				} else if (height_tmp > standardHeight) {
					float ratio = (float) height_tmp / standardHeight;
					finalWidth = (int) (width_tmp / ratio);
					finalHeight = standardHeight;
				} else {
					reducedBM.compress(CompressFormat.JPEG, 50, out);
					return true;
				}

				reducedBM = Bitmap.createScaledBitmap(reducedBM, finalWidth, finalHeight, true);
				reducedBM.compress(CompressFormat.JPEG, 50, out);

			} finally {
				out.close();
			}
		} catch (IOException e) {
			result = false;
		}
		return result;
	}

	public synchronized static int getExifOrientation(String filepath) {
		int degree = 0;
		ExifInterface exif = null;

		try {
			exif = new ExifInterface(filepath);
		} catch (IOException e) {
			Log.e("Mas", "cannot read exif");
			e.printStackTrace();
		}

		if (exif != null) {
			int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
			if (orientation != -1) {
				// We only recognize a subset of orientation tag values.
				switch (orientation) {
				case ExifInterface.ORIENTATION_ROTATE_90:
					degree = 90;
					break;

				case ExifInterface.ORIENTATION_ROTATE_180:
					degree = 180;
					break;
				case ExifInterface.ORIENTATION_ROTATE_270:
					degree = 270;
					break;
				}
			}
		}

		return degree;
	}

	public synchronized static Bitmap getRotatedBitmap(Bitmap bitmap, int degrees) {
		if (degrees != 0 && bitmap != null) {
			Matrix m = new Matrix();
			m.setRotate(degrees, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
			try {
				Bitmap b2 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
				if (bitmap != b2) {
					bitmap.recycle();
					bitmap = b2;
				}
			} catch (OutOfMemoryError ex) {
				// We have no memory to rotate. Return the original bitmap.
			}
		}

		return bitmap;
	}

	public static void deleteTmpFile(Uri uri) {
		if (uri == null) {
			return;
		}
		File file = new File(uri.getPath());
		file.delete();
	}

}
